package com.cps.frameuploadload.util;

import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.cps.framecommon.domain.vo.LoadInfo;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * <h5>描述:获取系统各类信息</h5>
 *
 * @author 11202
 */
@Slf4j
public class ToolOsInfo {
    public static void main(String[] args) {
        //获取cpu利用率
        double cpuInfo = getCpuAvailable();
        //获取内存数据
        double memoryInfo = getMemoryAvailable();
        //获取硬盘使用量
        getDiskUsed();
        System.out.println("===========");
        System.out.println("cpu可用率：" + cpuInfo);
        System.out.println("内存可用率：" + memoryInfo);
        System.out.println("ip地址:" + getLocalIp4Address());
    }


    /**
     * 获取cpu可用率
     */
    public static double getCpuAvailable() {
        CpuInfo cpuInfo = OshiUtil.getCpuInfo(3000);
        double free = cpuInfo.getFree();
        DecimalFormat format = new DecimalFormat("#.00");
//        System.out.println("cpu可用率：" + Double.parseDouble(format.format(free)));
        return Double.parseDouble(format.format(free));
    }

    public static void setCpuInfo(LoadInfo loadInfo) {
        CpuInfo cpuInfo = OshiUtil.getCpuInfo(3000);
        double free = cpuInfo.getFree();
        DecimalFormat format = new DecimalFormat("#.00");
        loadInfo.setCpuAvailable(Double.parseDouble(format.format(free)));
    }


    /**
     * 获取内存可用率
     */
    public static double getMemoryAvailable() {
        long total = OshiUtil.getMemory().getTotal();
        long available = OshiUtil.getMemory().getAvailable();
//        System.out.println("内存总量：" + total / 1024 / 1024/1024);
//        System.out.println("可用内存：" + available / 1024 / 1024/1024);
        return formatDouble(available, total);
    }

    public static long getTotalMemory() {
        long total = OshiUtil.getMemory().getTotal();
        return total / 1024 / 1024/1024;
    }
    public static Long getAvailableMemory() {
        long available = OshiUtil.getMemory().getAvailable();
        return available / 1024 / 1024/1024;
    }

    private static double formatDouble(long tick, long total) {
        return 0L == total ? 0.0 : Double.parseDouble(new DecimalFormat("#.00").format(tick <= 0L ? 0.0 : 100.0 * (double) tick / (double) total));
    }

    /**
     * 获取硬盘使用量
     */
    public static void getDiskUsed() {
        File win = new File("/");
        if (win.exists()) {
            long total = win.getTotalSpace();
            long freeSpace = win.getFreeSpace();
            System.out.println("磁盘总量：" + total / 1024 / 1024 / 1024);
            System.out.println("磁盘剩余总量：" + freeSpace / 1024 / 1024 / 1024);
            System.out.println("磁盘已用总量：" + (total - freeSpace) / 1024 / 1024 / 1024);
        }
    }

    public static String getLocalIp4Address() {
        final List<Inet4Address> ipByNi;
        try {
            ipByNi = getLocalIp4AddressFromNetworkInterface();
        } catch (SocketException e) {
            log.error("获取本机IP地址失败", e);
            return "";
        }
//        if (ipByNi.isEmpty() || ipByNi.size() > 1) {
//            final Optional<Inet4Address> ipBySocketOpt = getIpBySocket();
//            if (ipBySocketOpt.isPresent()) {
//                return ipBySocketOpt;
//            } else {
//                return ipByNi.isEmpty() ? Optional.empty() : Optional.of(ipByNi.get(0));
//            }
//        }
//        return Optional.of(ipByNi.get(0));
        return ipByNi.isEmpty() ? "" : ipByNi.get(0).getHostAddress();
    }

    public static List<Inet4Address> getLocalIp4AddressFromNetworkInterface() throws SocketException {
        List<Inet4Address> addresses = new ArrayList<>(1);
        Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
        while (e.hasMoreElements()) {
            NetworkInterface n = e.nextElement();
            if (!isValidInterface(n)) {
                continue;
            }
            Enumeration<InetAddress> ee = n.getInetAddresses();
            while (ee.hasMoreElements()) {
                InetAddress i = ee.nextElement();
                if (isValidAddress(i)) {
                    addresses.add((Inet4Address) i);
                }
            }
        }
        return addresses;
    }

    /**
     * 过滤回环网卡、点对点网卡、非活动网卡、虚拟网卡并要求网卡名字是eth或ens开头
     *
     * @param ni 网卡
     * @return 如果满足要求则true，否则false
     */
    private static boolean isValidInterface(NetworkInterface ni) throws SocketException {
        return !ni.isLoopback() && !ni.isPointToPoint() && ni.isUp() && !ni.isVirtual()
                && (ni.getName().startsWith("eth") || ni.getName().startsWith("ens") || ni.getName().startsWith("en"));
    }

    /**
     * 判断是否是IPv4，并且内网地址并过滤回环地址.
     */
    private static boolean isValidAddress(InetAddress address) {
        return address instanceof Inet4Address && address.isSiteLocalAddress() && !address.isLoopbackAddress();
    }

}
